/*
 * CastDRAndroid
 * Copyright (c) 2014 Christian Holm Christensen
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * Definition of RestClient
 */
package org.cholm.media.castdr.backend;

import android.webkit.URLUtil;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.net.URI;

import org.cholm.media.castdr.LogUtils; import static org.cholm.media.castdr.LogUtils.LOGd;
import static org.cholm.media.castdr.LogUtils.LOGe;
import static org.cholm.media.castdr.LogUtils.LOGw;
// import org.apache.commons.logging.LogFactory;
// import org.apache.commons.logging.Log;
// import org.apache.log4j.Level;
// import org.apache.log4j.LOGer;

/**
 * A client to do REST GET queries
 *
 * @author cholm
 */
public class RestClient {
    private static final String TAG = LogUtils.makeLogTag(RestClient.class);

    /**
     * Our client
     */
    protected HttpClient mClient = new DefaultHttpClient();

    /**
     * Desctructor called by garbage collector
     */
    public void finalize() {
        if (mClient != null) {
            LOGw(TAG,"Client not closed yet!");
            close();
        }
    }

    /**
     * Close the client
     */
    public void close() {
        mClient.getConnectionManager().shutdown();
        mClient = null;
    }

    /*
     * This is a test function which will connects to a given
     * rest service and prints it's response the output
     */
    public Result get(String url) {
        if (url == null || url.isEmpty()) {
            LOGw(TAG, "No URL specified");
            return null;
        }
        if (!URLUtil.isValidUrl(url)) {
            LOGw(TAG, "URL " + url + " is invalid");
            return null;
        }
        // Make client if needed
        if (mClient == null) mClient = new DefaultHttpClient();

        // Our return value
        Result json = null;

        // Prepare a request object
        URI uri = null;
        try {
            uri = URI.create(url);
        } catch (IllegalArgumentException e) {
            LOGw(TAG, "Failed to encode URI: " + e.getMessage(), e);
            return json;
        }
        HttpGet get = new HttpGet(uri);
        LOGd(TAG, "Doing query " + get.getURI().toString());

        // Execute the request
        try {
            HttpResponse response = mClient.execute(get);
            // Examine the response status
            LOGd(TAG,"Response: " + response.getStatusLine().toString());

            // Get hold of the response entity
            HttpEntity entity = response.getEntity();
            // If the response does not enclose an entity, there is no need
            // to worry about connection release

            if (entity != null) {
                String result = EntityUtils.toString(entity);
                // System.out.println(result);
                entity.consumeContent();

                // A Simple JSONObject Creation
                json = new RestClient.Result();
                try {
                    json.mObject = new JSONObject(result);
                } catch (JSONException e) {
                    LOGw(TAG,"Failed to decode JSON", e);
                    json.mObject = null;
                }
                try {
                    if (json.mObject == null) json.mArray = new JSONArray(
                            result);
                } catch (JSONException e) {
                    LOGw(TAG,"Failed to make object", e);
                    json.mArray = null;
                }
            }
        } catch (ClientProtocolException e) {
            LOGe(TAG,"Protocol error", e);
        } catch (IOException e) {
            LOGe(TAG,"I/O error", e);
        } finally {
            // get.releaseConnection();

        }

        // Return to caller
        return json;
    }

    /**
     * Print retrieved result
     *
     * @param json
     */
    public void print(Result json) {
        try {
            if (json.mObject != null) LOGd(TAG,json.mObject.toString(2));
            if (json.mArray != null) LOGd(TAG,json.mArray.toString(2));
        } catch (JSONException e) {
            LOGe(TAG,"Didn't get object or array",e);
        }
    }
    // protected Log log = LogFactory.getLog(RestClient.class);

    /**
     * The result of the query. It can be an object or an array, but not both.
     *
     * @author cholm
     */
    public static class Result {
        /**
         * Object result
         */
        public JSONObject mObject = null;
        /**
         * Array result
         */
        public JSONArray mArray = null;
    }

    /**
     * Our log
     */
    class MyLog {
        public void warn(String o) {
            LOGw("RestClient", o);
        }

        public void error(String o) {
            LOGe("RestClient", o);
        }

        public void debug(String o) {
            LOGd("RestClient", o);
        }

        public void error(String o, Throwable e) {
            LOGe("RestClient", o, e);
        }
    }

}
// EOF
